package com.california.pay.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.california.pay.common.id.IdWorker;
import com.california.pay.common.utils.DateUtils;
import com.california.pay.common.utils.RandomUtil;
import com.california.pay.config.CommonErrors;
import com.california.pay.consts.LoginStatus;
import com.california.pay.consts.Status;
import com.california.pay.exception.BusinessException;
import com.california.pay.persist.domain.MchPayQuota;
import com.california.pay.persist.domain.PayPersonMch;
import com.california.pay.persist.domain.Terminal;
import com.california.pay.persist.domain.TerminalLogin;
import com.california.pay.persist.mapper.MchPayQuotaMapper;
import com.california.pay.persist.mapper.PayPersonMchMapper;
import com.california.pay.persist.mapper.TerminalLoginMapper;
import com.california.pay.persist.mapper.TerminalMapper;
import com.california.pay.socket.NettyChannelMap;
import com.california.pay.socket.TransSocketMessage;
import com.google.common.collect.Maps;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Map;


@Slf4j
@Service
public class TerminalLoginService {
    @Autowired
    private TerminalMapper terminalMapper;
    @Autowired
    private TerminalLoginMapper loginMapper;
    @Autowired
    private PayPersonMchMapper personMchMapper;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private MchPayQuotaMapper payQuotaMapper;

    @Transactional(rollbackFor = {Exception.class})
    public Map<String, String> login(TransSocketMessage socketMessage, Channel channel) {
        String message = socketMessage.getMessage();
        if (StringUtils.isBlank(message)) {
            throw new BusinessException(CommonErrors.INVALID_PARAM, "注册接口，message不为空");
        }

        Map<String, String> msgMap = JSON.parseObject(message, new TypeReference<Map<String, String>>() {
        });

        String clientId = msgMap.get("clientId");
        //String clientTime = msgMap.get("clientTime");
        String channelUserId = msgMap.get("channelUserId");

        Terminal terminal = getOrCreateTerminal(clientId);
        PayPersonMch personMch = getPayPersonMch(channelUserId);
        TerminalLogin terminalLogin = createLogin(terminal, personMch, channel);
        checkChannelMchQuota(personMch);

        Map<String, String> rspMap = Maps.newHashMap();
        rspMap.put("sessionId", terminalLogin.getSessionId());
        rspMap.put("appKey", terminalLogin.getAppKey());
        rspMap.put("clientId", clientId);

        NettyChannelMap.addChannel(channel.id().asLongText().toString(), channel);


        return rspMap;
    }

    @Transactional(rollbackFor = {Exception.class})
    public void checkChannelMchQuota(PayPersonMch personMch) {
        Date now = new Date();
        MchPayQuota query = new MchPayQuota();
        query.setChannelMchId(personMch.getPersonMchId());
        Long payDate = Long.parseLong(DateUtils.yyyyMMdd(now));
        query.setPayDate(payDate);

        MchPayQuota record = payQuotaMapper.selectOne(query);
        if (record == null) {
            record = new MchPayQuota();
            record.setQuotaId(idWorker.nextIdString());
            record.setChannelMchId(personMch.getPersonMchId());
            record.setPayTotalAmount(0L);
            record.setPayDate(payDate);
            record.setCreateTime(now);
            record.setUpdateTime(now);
            record.setVersion(0);
            record.setStatus(Status.USABLE);
            payQuotaMapper.insertSelective(record);
        }else{
            payQuotaMapper.updateStatusByChannelMchId(Status.USABLE, personMch.getPersonMchId(), payDate);
        }
    }


    public String getAppKey(String clientId) {
        TerminalLogin query = new TerminalLogin();
        query.setClientId(clientId);

        TerminalLogin record = loginMapper.selectOne(query);
        if (record == null) {
            throw new BusinessException(CommonErrors.CLIENT_UN_LOGIN, "当前终端未登录");
        }

        return record.getAppKey();
    }

    private TerminalLogin createLogin(Terminal terminal, PayPersonMch personMch, Channel channel) {
        TerminalLogin query = new TerminalLogin();
        query.setClientId(terminal.getClientId());
        TerminalLogin record = loginMapper.selectOne(query);

        if (record != null) {
            loginMapper.deleteByPrimaryKey(record.getLoginId());
        }

        Date now = new Date();
        TerminalLogin login = new TerminalLogin();
        login.setLoginId(idWorker.nextIdString());
        login.setChannelMchId(personMch.getPersonMchId());
        login.setChannelUserId(personMch.getChannelUserId());
        login.setTerminalId(terminal.getTerminalId());
        login.setClientId(terminal.getClientId());
        login.setSessionId(RandomUtil.generateNumString(6));
        login.setAppKey(RandomUtil.generateMixString(32));
        login.setLoginTime(now);
        login.setLoginStatus(LoginStatus.LOGIN);
        login.setCreateTime(now);
        login.setUpdateTime(now);
        login.setNettyChannelId(channel.id().asLongText());
        loginMapper.insertSelective(login);


        return login;
    }

    public TerminalLogin getTerminalLogin(String clientId) {
        TerminalLogin query = new TerminalLogin();
        query.setClientId(clientId);
        query.setLoginStatus(LoginStatus.LOGIN);
        TerminalLogin login = loginMapper.selectOne(query);
        return login;
    }

    public Terminal getOrCreateTerminal(String clientId) {
        Terminal query = new Terminal();
        query.setClientId(clientId);
        query.setState(Status.USABLE);

        Terminal terminal = terminalMapper.selectOne(query);
        if (terminal == null) {
            terminal = new Terminal();
            terminal.setTerminalId(idWorker.nextIdString());
            terminal.setClientId(clientId);
            terminal.setAppKey("NONE");
            terminal.setState(Status.USABLE);
            terminal.setTerminalType("安卓");
            terminal.setRemark("终端登录时填写");
            terminal.setCreateTime(new Date());
            terminal.setUpdateTime(new Date());
            terminalMapper.insertSelective(terminal);
            return terminal;
        }
        return terminal;
    }

    public PayPersonMch getPayPersonMch(String channelUserId) {
        PayPersonMch query = new PayPersonMch();
        query.setChannelUserId(channelUserId);
        PayPersonMch personMch = personMchMapper.selectOne(query);
        if (personMch == null) {
            throw new BusinessException(CommonErrors.CLIENT_UN_REGISTER, "渠道个人商户未在管理台注册");
        }
        return personMch;

    }

    @Transactional(rollbackFor = {Exception.class}, propagation = Propagation.REQUIRES_NEW)
    public void logout(Channel channel, String nettyChannelId) {
        NettyChannelMap.removeChannelByName(nettyChannelId);

        Date now = new Date();
        TerminalLogin query = new TerminalLogin();
        query.setNettyChannelId(nettyChannelId);
        TerminalLogin login = loginMapper.selectOne(query);

        if (login == null) {
            //throw new BusinessException(CommonErrors.CLIENT_UN_LOGIN, "未找到当前终端登录对象");
            return;
        }
        loginMapper.deleteByPrimaryKey(login.getLoginId());
        payQuotaMapper.updateStatusByChannelMchId(Status.DISABLE, login.getChannelMchId(), Long.parseLong(DateUtils.yyyyMMdd(now)));
    }

    @Transactional(rollbackFor = {Exception.class}, propagation = Propagation.REQUIRES_NEW)
    public void closeTerminlogin(TerminalLogin terminalLogin) {
        String channelMchId = terminalLogin.getChannelMchId();
        payQuotaMapper.updateStatusByChannelMchId(Status.DISABLE, channelMchId, Long.parseLong(DateUtils.yyyyMMdd(new Date())));
        loginMapper.deleteByChannelMchId(channelMchId);
    }


}
